<?php
/**
 * Created by PhpStorm.
 * User: Season
 * Date: 2018/10/20
 * Time: 17:26
 */

namespace app\api\service;


use app\lib\enum\ScopEnum;
use app\lib\exception\TokenException;
use app\lib\exception\WeChatException;
use think\Exception;
use app\api\model\User as UserModel;
class UserToken extends Token
{
    protected $code;
    protected $wxAppID;
    protected $wxAppSecret;
    protected $wxLoginUrl;

    function __construct ($code)
    {
        $this->code = $code;
        $this->wxAppID = config ('wx.appID');
        $this->wxAppSecret = config ('wx.appSecret');
        $this->wxLoginUrl = sprintf (config ('wx.loginUrl'),
                                     $this->wxAppID,$this->wxAppSecret,$this->code);
    }

    public function get(){
        $result = curl ($this->wxLoginUrl);
        $wxResult = json_decode ($result,true);
        if(empty($wxResult)){
            throw new Exception('获取session_key及openID异常,微信内部错误');
        }
        else{
            $loginFail = array_key_exists ('errcode',$wxResult);
            if($loginFail){
                //微信返回有异常
                $this->processLogInError ($wxResult);
            }
            else{
                //无异常颁发令牌
                return $this->grantToken ($wxResult);
            }
        }
    }

    //颁发token
    private function grantToken($wxResult){
        //拿到openid
        $openid = $wxResult['openid'];
        $user = UserModel::getByOpenID ($openid);
        if($user){
            $uid = $user->id;
        }else{
            //新用户增加一条数据
            $uid = $this->newUser ($openid);
        }
        //查询openid是否存在
        $cacheValue = $this->prepareCachedValue ($wxResult,$uid);
        $token = $this->saveToCache ($cacheValue);
        return $token;
    }

    private function newUser($openid){
        $user = UserModel::create ([
            'openid'=>$openid
           ]);
        return $user->id;
    }

    private function  prepareCachedValue($wxResult,$uid){
        $cachedValue = $wxResult;
        $cachedValue['uid'] = $uid;
        $cachedValue['scope'] = ScopEnum::User;
        return $cachedValue;
    }

    private function processLogInError($wxResult){
        throw new WeChatException([
                'msg' => $wxResult['errmsg'],
                'errorCode' => $wxResult['errcode']
            ]);
    }

    private static function saveToCache($cacheValue){
        $key = self::generateToken ();
        $value = json_encode ($cacheValue);
        $expire_in = config ('setting.token_expire_in');
        $request = cache ($key , $value , $expire_in);
        if(!$request){
            throw new TokenException([
                'msg'=>'服务器缓存异常',
                'errorCode'=>10005
                                     ]);
        }
        return $key;
    }
}